#include "head.h"

// 功能：建立TCP连接
int establishConnect(char *ip, char *port){
    
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    
    struct sockaddr_in saddr;
    saddr.sin_addr.s_addr = inet_addr(ip);
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(atoi(port));

    int flag = 1;
    int ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));
    ERROR_CHECK(ret, -1, "opt");

    ret = bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr));
    ERROR_CHECK(ret, -1, "bind");
    
    listen(sockfd, 10);

    return sockfd;
}

// 功能：建立连接
int establishConnectWithDownLoader(const char *ip,const char *port){
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);

    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = inet_addr(ip);
    saddr.sin_port = htons(atoi(port));

    int ret = connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr));
    ERROR_CHECK(ret, -1, "connect");

    return sockfd;
}

// 功能：添加监听
int epollAdd(int efd, int monitorfd){
    
    struct epoll_event event;
    bzero(&event, sizeof(event));

    event.data.fd = monitorfd;
    event.events = EPOLLIN;

    epoll_ctl(efd, EPOLL_CTL_ADD, monitorfd, &event);

    return 0;

}

int epollDel(int efd, int delfd){
    epoll_ctl(efd, EPOLL_CTL_DEL, delfd, NULL);
    return 0;
}

// 功能：添加监听，并将文件描述加入超时队列
int epollAddTime(int efd, int sockfd, timeOutTool_t *timeOutQueue){
    int curTime = time(NULL);
    fdNode_t *fdNode = (fdNode_t *)calloc(1, sizeof(fdNode_t));
    fdNode->netfd = sockfd;
    fdNode->curIndex = curTime % TIMEOUT; 

    struct epoll_event event;
    event.events = EPOLLIN;
    event.data.ptr = fdNode;
    epoll_ctl(efd, EPOLL_CTL_ADD, sockfd, &event);

    addNodeInTimeOutTool(&timeOutQueue[curTime % TIMEOUT], fdNode);
    return 0;
}

// 功能：添加node到超时计时器组                        
int addNodeInTimeOutTool(timeOutTool_t *tool, fdNode_t *node){
    ++tool->len;
    if(tool->len == 1){
        // 首个结点
        tool->head = node;
        return 0;
    }
    // 其余情况
    node->next = tool->head;
    tool->head->pre = node;
    node->pre = NULL;
    tool->head = node;
    return 0;
}
                                                       
// 功能：将指定node从超时计时器组中剔除                
int delNodeInTimeOutTool(timeOutTool_t *tool, fdNode_t *node){
    if(tool->len == 0){
        return 0;
    }
    --tool->len;
    // 单一个结点的情况
    if(tool->len == 0){
        tool->head = NULL;
        return 0;
    } 
    // 该结点是头结点的情况
    if(tool->head == node){
        tool->head = node->next;
        tool->head->pre = NULL;
        node->next = NULL;
        return 0;
    }
    
    // 该结点是尾结点的情况
    if(node->next == NULL){
        node->pre->next = NULL;
        node->pre = NULL;
        return 0;
    }
    // 该结点是中间结点
    fdNode_t *preNode = node->pre;
    preNode->next = node->next;
    node->next->pre = preNode;
    node->pre = NULL;
    node->next = NULL;

    return 0;
}



// 功能：回复响应                  
int TLVResponse(int sockfd, const char *buf, int type){
    train_t train;
    bzero(&train, sizeof(train));

    train.type = type;
    train.len =strlen(buf);
    memcpy(train.buf, buf, train.len);

    int ret = send(sockfd, &train, sizeof(int) * 2 + train.len, MSG_NOSIGNAL);
    if(ret <= 0){
        return -1;
    }
    return 0;
}

// 功能：文件传输时响应长度信息
//int TLVResponseLen(int sockfd, int len){
//    train_t train;
//    bzero(&train, sizeof(train));
//
//    train.type = FILE_LEN;
//    train.len = len;
//
//    send(sockfd, &train, sizeof(int)*2, MSG_NOSIGNAL);
//
//    return 0;
//}
                                   
// 功能：接收请求                  
//int recvRequest(int sockfd, train_t *train){
//    bzero(train, sizeof(train_t));
//
//    int ret = recv(sockfd, &train->type, sizeof(int), MSG_WAITALL);
//    if(train->type == LS || train->type == PWD){
//        return 0;
//    }
//    ret = recv(sockfd, &train->len, sizeof(int), MSG_WAITALL);
//    // 传送的是文件大小
//    if(train->type != FILE_LEN){
//        ret = recv(sockfd, train->buf, train->len, MSG_WAITALL);
//    }
//
//    if(ret <= 0){
//        return -1;
//    }
//    return 0;
//}

int recvRequest(int sockfd, train_t *train){
    bzero(train, sizeof(train_t));

    int ret = recv(sockfd, &train->type, sizeof(int), MSG_WAITALL);
    if(ret <= 0){
        return -1;
    }
    recv(sockfd, &train->len, sizeof(int), MSG_WAITALL);
    if(train->len){
        recv(sockfd, train->buf, train->len, MSG_WAITALL);
    }
    return 0;
}




int recvOrderTrain(int sockfd, train_t *train){
    bzero(train, sizeof(train_t));

    int ret = recv(sockfd, &train->type, sizeof(int), MSG_WAITALL);
    if(ret <= 0){
        return -1;
    }
    recv(sockfd, &train->len, sizeof(int), MSG_WAITALL);
    if(train->len){
        recv(sockfd, train->buf, train->len, MSG_WAITALL);
    }
    return 0;
}

